
#include <iostream>
using namespace std;
#include <cstring>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cassert>
#include <unordered_map>
#include <vector>

typedef void (*functor)();
vector<functor> functors;
unordered_map<uint32_t, string> info;

//  进程pid   进程对应打开端的fd
typedef std::pair<uint32_t, uint32_t> elem;
int processNum = 5;
void f1()
{
  cout << "这是一个处理日志的任务, 执行的进程 ID [" << getpid() << "]"
       << "执行时间是[" << time(nullptr) << "]\n"
       << endl;
}
void f2()
{
  cout << "这是一个备份数据任务, 执行的进程 ID [" << getpid() << "]"
       << "执行时间是[" << time(nullptr) << "]\n"
       << endl;
}
void f3()
{
  cout << "这是一个处理网络连接的任务, 执行的进程 ID [" << getpid() << "]"
       << "执行时间是[" << time(nullptr) << "]\n"
       << endl;
}
void loadFunctor()
{
  info.insert({functors.size(), "处理日志的任务"});
  functors.push_back(f1);

  info.insert({functors.size(), "备份数据任务"});
  functors.push_back(f2);

  info.insert({functors.size(), "处理网络连接的任务"});
  functors.push_back(f3);
}
void work(int blockFd)
{
  cout<<"进程["<<getpid()<<"]"<<"开始工作"<<endl;
  while (true)
  {
    uint32_t operatorCode = 0;
    int s = read(blockFd, &operatorCode, sizeof(uint32_t));
    if(s==0)
    {
      break;
    }
    assert(s == sizeof(uint32_t));
    (void)s;
    if (operatorCode < functors.size())
    {
      functors[operatorCode]();
    }
    else
    {
      cerr << "bug" << endl;
    }
  }
  cout<<"进程["<<getpid()<<"]"<<"结束工作~~~~~"<<endl;
}
void balanceSendTask(const vector<elem> &processFds)
{
  srand((unsigned int)time(nullptr));
  while (true)
  {
    sleep(1);
    uint32_t pick = rand() % processFds.size();
    uint32_t task = rand() % functors.size();
    write(processFds[pick].second, &task, sizeof(uint32_t));
    cout << "父进程指派任务->" << info[task]
         << " 给进程：" << processFds[pick].first << " 编号：" 
            << pick << endl;
  }
}

int main()
{
  loadFunctor();
  vector<elem> assignMap;
  while (processNum--)
  {
    int pipefd[2];
    if (pipe(pipefd) != 0)
    {
      cerr << "pipe error" << endl;
      return 1;
    }
    pid_t id = fork();
    if (id < 0)
    {
      cerr << "fork error" << endl;
    }
    else if (id == 0)
    {
      close(pipefd[1]);
      work(pipefd[0]);
      close(pipefd[0]);
      exit(0);
    }
    //下面都是父进程的任务了：——————————
    close(pipefd[0]);
    elem e(id, pipefd[1]);
    assignMap.push_back(e);
  }
  balanceSendTask(assignMap);
  //回收资源
  for (int i = 0; i < processNum; i++)
  {
    if (waitpid(assignMap[i].first, nullptr, 0) > 0)
    {
      cout << "wait for pid= " << assignMap[i].first << " wait success"
           << "number: " << i << endl;
      close(assignMap[i].second);
    }
  }
  return 0;
}
